home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / server / pets.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  8KB  |  258 lines

  1. /*
  2.  * static char *rcsid_pets_c =
  3.  *    "$Id: pets.c,v 1.8 1994/12/30 07:58:14 master Exp $";
  4.  */
  5.  
  6. /*
  7.     CrossFire, A Multiplayer game for X-windows
  8.  
  9.     Copyright (C) 1992 Frank Tore Johansen
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.     The author can be reached via e-mail to frankj@ifi.uio.no.
  26. */
  27.  
  28. #include <global.h>
  29. #ifndef __CEXTRACT__
  30. #include <sproto.h>
  31. #endif
  32.  
  33. void add_pending_object(object *ob, mapstruct *map) {
  34.   objectlink *obl;
  35.  
  36.   if(ob->arch == NULL) {
  37.     LOG(llevError,"Can't add pending object without arch: %s\n",ob->name);
  38.     return;
  39.   }
  40.   LOG(llevDebug,"Adding pending object %s to %s\n",ob->name,map->path);
  41.   obl = (objectlink *) malloc(sizeof(objectlink));
  42.   ob->speed = 0;
  43.   update_ob_speed(ob);
  44.  
  45.   obl->ob = ob;
  46.   obl->next = map->pending;
  47.   map->pending=obl;
  48. }
  49.  
  50. void enter_pending_objects(mapstruct *map) {
  51.   objectlink *obl, *next;
  52.   object *owner;
  53.  
  54.   if(map->in_memory != MAP_IN_MEMORY) {
  55.     LOG(llevError,"Can't enter pending objects: map not in memory.\n");
  56.     return;
  57.   }
  58.   for(obl = map->pending; obl!= NULL; obl = next) {
  59.     next = obl->next;
  60.     LOG(llevDebug,"Entering pending %s in %s\n",obl->ob->name,map->path);
  61.     if(obl->ob->type == PLAYER) {
  62.       fix_player(obl->ob);
  63.       insert_ob_in_map(obl->ob,map);
  64.     }
  65.     if (obl->ob->arch != NULL && obl->ob->type != PLAYER) {
  66.     obl->ob->speed = obl->ob->arch->clone.speed;
  67.     update_ob_speed(obl->ob);
  68.     }
  69.     if((owner = get_owner(obl->ob)) != NULL)
  70.       follow_owner(obl->ob,owner);
  71.     if(QUERY_FLAG(obl->ob, FLAG_REMOVED)) {
  72.       LOG(llevDebug,"follow_owner didn't help.\n");
  73.       insert_ob_in_map(obl->ob,map);
  74.     }
  75.     free(obl);
  76.   }
  77.   map->pending = NULL;
  78. }
  79.  
  80. object *get_pet_enemy(object * pet){
  81.   object         *owner, *tmp;
  82.   int             i;
  83.   if ((owner = get_owner(pet)) != NULL) {
  84.     if ((get_enemy(owner)) == pet) {
  85.       CLEAR_FLAG(pet, FLAG_FRIENDLY);
  86.       remove_friendly_object(pet);
  87.       pet->move_type &=~PETMOVE;
  88.       return owner;
  89.     }
  90.   } else { /* No point in keeping it friendly  */
  91.     CLEAR_FLAG(pet, FLAG_FRIENDLY);
  92.     remove_friendly_object(pet);
  93.     pet->move_type &=~PETMOVE;
  94.     return NULL;
  95.   }
  96.   if (owner->map != pet->map)
  97.       return NULL;
  98.   for (i = 0; i < SIZEOFFREE; i++)
  99.     if (out_of_map(owner->map, owner->x + freearr_x[i],
  100.                    owner->y + freearr_y[i]))
  101.        continue;
  102.     else
  103.       for (tmp = get_map_ob(owner->map, owner->x + freearr_x[i],
  104.            owner->y + freearr_y[i]); tmp != NULL; tmp = tmp->above)
  105.         if (tmp == NULL)
  106.           continue;
  107.         else  {
  108.           object *tmp2 = tmp->head == NULL?tmp:tmp->head;
  109.           if (QUERY_FLAG(tmp2,FLAG_ALIVE) && !QUERY_FLAG(tmp2,FLAG_FRIENDLY)
  110.         && !QUERY_FLAG(tmp2,FLAG_UNAGGRESSIVE) &&
  111.                  tmp2 != owner && tmp2->type != PLAYER)
  112.           return tmp2;
  113.         }
  114.   return NULL;
  115. }
  116.  
  117. void terminate_all_pets(object *owner) {
  118.   objectlink *obl, *next;
  119.   for(obl = first_friendly_object; obl != NULL; obl = next) {
  120.     object *ob = obl->ob;
  121.     next = obl->next;
  122.     if(get_owner(ob) == owner) {
  123.       if(!QUERY_FLAG(ob, FLAG_REMOVED))
  124.         remove_ob(ob);
  125.       remove_friendly_object(ob);
  126.       free_object(ob);
  127.     }
  128.   }
  129. }
  130.  
  131. /*
  132.  * Unfortunately, sometimes, the owner of a pet is in the
  133.  * process of entering a new map when this is called.
  134.  * Thus the map isn't loaded yet, and we have to remove
  135.  * the pet...
  136.  */
  137.  
  138. void remove_all_pets(mapstruct *map) {
  139.   objectlink *obl, *next;
  140.   object *owner;
  141.  
  142.   for(obl = first_friendly_object; obl != NULL; obl = next) {
  143.     next = obl->next;
  144.     if(obl->ob->type != PLAYER && QUERY_FLAG(obl->ob,FLAG_FRIENDLY) &&
  145.        (owner = get_owner(obl->ob)) != NULL && owner->map != obl->ob->map)
  146.     {
  147.       if(owner->map == NULL || owner->map->in_memory != MAP_IN_MEMORY) {
  148.         object *ob = obl->ob;
  149.         if(owner->map != NULL) {
  150.           remove_ob(ob);
  151.           add_pending_object(ob, owner->map);
  152.           continue;
  153.         }
  154.         LOG(llevMonster,"(pet no map)..");
  155.         remove_ob(ob);
  156.         remove_friendly_object(ob);
  157.         free_object(ob);
  158.         continue;
  159.       }
  160.       follow_owner(obl->ob,owner);
  161.       if(QUERY_FLAG(obl->ob, FLAG_REMOVED) && FABS(obl->ob->speed) > 0.00001) {
  162.         object *ob = obl->ob;
  163.         LOG(llevMonster,"(pet failed to follow)");
  164.         remove_friendly_object(ob);
  165.         free_object(ob);
  166.       }
  167.     }
  168.   }
  169. }
  170.  
  171. void follow_owner(object *ob, object *owner) {
  172.   object *tmp;
  173.   int dir;
  174.  
  175.   if (!QUERY_FLAG(ob,FLAG_REMOVED))
  176.     remove_ob(ob);
  177.   if(owner->map == NULL) {
  178.     LOG(llevError,"Can't follow owner: no map.\n");
  179.     return;
  180.   }
  181.   if(owner->map->in_memory != MAP_IN_MEMORY) {
  182.     LOG(llevMonster,"Map loading, adding pending object (%s).\n",ob->name);
  183.     add_pending_object(ob,owner->map);
  184.     return;
  185.   }
  186.   dir = find_free_spot(ob->arch, owner->map,
  187.                        owner->x, owner->y, 1, SIZEOFFREE);
  188.   if (!dir) {
  189.     LOG(llevMonster,"No space for pet to follow, freeing %s.\n",ob->name);
  190.     return; /* Will be freed since it's removed */
  191.   }
  192.   for(tmp=ob;tmp!=NULL;tmp=tmp->more) {
  193.     tmp->x = owner->x + freearr_x[dir]+(tmp->arch==NULL?0:tmp->arch->clone.x);
  194.     tmp->y = owner->y + freearr_y[dir]+(tmp->arch==NULL?0:tmp->arch->clone.y);
  195.   }
  196.   insert_ob_in_map(ob, owner->map);
  197.   if (owner->type == PLAYER) /* Uh, I hope this is always true... */
  198.     new_draw_info(NDI_UNIQUE, 0,ob->owner, "Your pet magically appears next to you");
  199.   return;
  200. }
  201.  
  202. void pet_move(object * ob)
  203. {
  204.   int dir;
  205.   object *ob2, *owner;
  206.  
  207.   /* Check to see if player pulled out */
  208.   if ((owner = get_owner(ob)) == NULL) {
  209.     remove_ob(ob); /* Will be freed when returning */
  210.     LOG(llevMonster, "Pet: no owner, leaving.\n");
  211.     return;
  212.   }
  213.  
  214.   /* move monster into the owners map if not in the same map */
  215.   if (ob->map != owner->map) {
  216.     follow_owner(ob, owner);
  217.     return;
  218.   }
  219.   /* Calculate Direction */
  220.   dir = find_dir_2(ob->x - ob->owner->x, ob->y - ob->owner->y);
  221.   ob->direction = dir;
  222.  
  223.   if (!(move_ob(ob, dir))) {
  224.     object *part;
  225.     for(part = ob; part != NULL; part = part->more)
  226.     {
  227.       for (ob2 = get_map_ob(part->map, part->x + freearr_x[dir],
  228.            part->y + freearr_y[dir]); ob2 != NULL; ob2 = ob2->above)
  229.       {
  230.         object *new_ob;
  231.         new_ob = ob2->head?ob2->head:ob2;
  232.         if(new_ob == ob)
  233.           break;
  234.         if (new_ob == ob->owner)
  235.           return;
  236.         if (get_owner(new_ob) == ob->owner)
  237.           break;
  238.         if (QUERY_FLAG(new_ob,FLAG_ALIVE) && !QUERY_FLAG(ob,FLAG_UNAGGRESSIVE)
  239.         && !QUERY_FLAG(new_ob,FLAG_UNAGGRESSIVE) &&
  240.             !QUERY_FLAG(new_ob,FLAG_FRIENDLY)) {
  241.           ob->enemy = new_ob;
  242.           if(new_ob->enemy == NULL)
  243.             new_ob->enemy = ob;
  244.           return;
  245.         } else if (new_ob->type == PLAYER) {
  246.           new_draw_info(NDI_UNIQUE, 0,new_ob, "You stand in the way of someones pet.");
  247.           return;
  248.         }
  249.       }
  250.     }
  251.     dir += 4 - (RANDOM() %5) - (RANDOM()%5);
  252.     if(QUERY_FLAG(ob,FLAG_IS_TURNING))
  253.       ob->value=(dir<5);
  254.     (void) move_ob(ob, dir);
  255.   }
  256.   return;
  257. }
  258.